#include "fileclient.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QFile>
#include <QFileInfo>
#include <QCryptographicHash>
#include "api.h"
FileClient::FileClient(QObject *parent)
    : QObject(parent),
      m_size(0)
{
    connect(&m_webSocket, &QWebSocket::connected, this, &FileClient::onConnected);
    connect(&m_webSocket, &QWebSocket::disconnected, this, &FileClient::closed);    
    connect(&m_webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
}

FileClient::~FileClient()
{
    qDebug() << "file client deleted";
}

void FileClient::setFilePos(qint64 pos)
{
    m_pos = pos;
}

void FileClient::setLength(qint64 length)
{
    m_length = length;
}

void FileClient::setFileName(const QString &fileName)
{
    m_file = new QFile(fileName, this);
    m_file->open(QIODevice::WriteOnly| QIODevice::Append);
    m_token = QCryptographicHash::hash(fileName.toUtf8(), QCryptographicHash::Md5).toHex();
}

void FileClient::open(const QUrl &url)
{
    m_webSocket.open(url);
}

void FileClient::onConnected()
{
    connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &FileClient::onTextMessageReceived);
    connect(&m_webSocket, &QWebSocket::binaryMessageReceived, this, &FileClient::onBinaryMessageReceived);
    connect(&m_webSocket, &QWebSocket::pong, this, &FileClient::processPong);
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(processTimerPingPong()));

    m_timer.setInterval(60000);
    m_timer.start();

    QJsonObject object;
    object.insert("status", "begin");
    object.insert("pos", m_pos);

    QJsonDocument document(object);
    m_webSocket.sendTextMessage(document.toJson());
}

void FileClient::onBinaryMessageReceived(const QByteArray &message)
{
    quint16 chksum = qChecksum(message, message.size());
    if (chksum !=  m_chksum) {
        QJsonObject object;
        object.insert("status", "repeat");
        m_webSocket.ping(QJsonDocument(object).toJson());
        return;
    }

    m_size += m_file->write(message);
    this->progress(m_size, m_length);
    qDebug() << "size:" << m_size << "receive size: " << message.length();
    // 接收完毕
    if (m_size == m_length) {
        QString fileName= m_file->fileName();
        QFileInfo fileInfo(fileName);
        QString newFileName = fileName;
        newFileName.chop(fileInfo.suffix().length() + 1);

        m_file->rename(newFileName);
        m_file->close();

        QString md5 = Api::fileMD5(newFileName);

        if (md5 != m_md5) {
            m_file->remove();
        }

        QJsonObject object;
        object.insert("status", "finish");
        m_webSocket.ping(QJsonDocument(object).toJson());

        m_webSocket.close();
    }
}

void FileClient::onTextMessageReceived(const QString &message)
{
    QJsonDocument document = QJsonDocument::fromJson(message.toUtf8());
    QJsonObject object = document.object();
    QString status = object.value("status").toString();

    qDebug() << "client " << status;
     if (status == "transport")
     {
         m_chksum = object.value("crc").toInt();

         QJsonObject sendobject;

         sendobject.insert("status", "continue");

         m_webSocket.sendTextMessage(QJsonDocument(sendobject).toJson());
     }
}

void FileClient::processPong(quint64 /*elapsedTime*/, const QByteArray & /*payload*/)
{
     m_pong = true;
}

void FileClient::processTimerPingPong()
{
    if (!m_pong) {
        m_webSocket.close();
    }
    else {
        m_pong = false;
        m_webSocket.ping();
    }
}

void FileClient::error(QAbstractSocket::SocketError error)
{
    qDebug() << "file client error:" << m_webSocket.errorString();
}
QString FileClient::token() const
{
    return m_token;
}

void FileClient::setSize(qint64 size)
{
    m_size = size;
}

void FileClient::setMD5(const QString &md5)
{
    m_md5 = md5;
}



